home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d13
/
phantz.arc
/
PHANT1.Z
/
PHANT1
Wrap
Text File
|
1991-06-06
|
61KB
|
2,088 lines
: ---------CUT HERE---------
: This is a shar archive. Extract with sh, not csh.
: The rest of this file will extract:
: README Makefile main.c include.h phantstruct.h map.c monsters.asc
echo x - README
sed 's/^X//' > README << '!EOR!'
XJune 25, 1986
X
X
XThis is a much modified version of Phantasia. It is intended to fix
Xall reported bug fixes, enhance the game, and speed up the game.
X
XI have to thank Chris Robertson for many ideas which have made the game
Xfaster, and more user-friendly. Most of her changes/additions are
Xincorporated in this latest versions, although perhaps not in the exact
Xmanner of her design. I left out a few items which were not in keeping
Xwith the spirit of the game. (For example, I didn't like the extra lives
Xand the pausing of the game. I think it's too easy even WITHOUT that stuff.)
X
XCHANGES:
X
X - Wormholes have been deleted (I never liked them anyway).
X - The source code has been greatly enhanced for speed, size, readability,
X and maintainability.
X fight.c should no longer cause optimizers to run out of space.
X - A few loopholes have been tightened to make the game more enjoyable.
X (Except for those who are in the habit of exercising those loopholes.)
X - Chris' map is enclosed.
X - The "charac" file is not compatible with older versions of Phantasia
X (3.3.1 and 3.3.1+). A 'convert' program is provided to convert your
X old file to the new format. See Makefile for details.
X - Movements can be made with HJKL for WSNE, respectively.
X - Players may examine others while playing ('x') option.
X - Monsters are now stored in a binary data base, to speed calling
X monsters, and to ease formatting of monster listings.
X - Taxes are collected on all gold and gems.
X - Dead players can be resurrected by the 'wizard'.
X - 'setup' is smarter, although not as smart as it should be.
X - Players can change their names and passwords
X
XPORTABILTY:
X
X I have tried to make this as non-machine/system specific as possible.
X
X All identifiers are unique to 7 characters or less, dual case.
X
X The code WILL NOT fit on a 16-bit machine without separate I/D.
X
X Stdio MUST support fopen() with mode "r+". I think this is true
X for all Version 7 and later.
X
X 'curses' library functions are required.
X
X All problems/solutions with portability should be reported to me,
X and fixes will be included in subsequent versions of this software.
X
X
XPlease send me any bugs, (of which I am sure there are many), you may find,
Xbut PLEASE be specific. I cannot correct a bug which is described as:
X
X "When I choose a character type, it blows up."
X
X (What blows up? What exactly was printed at the terminal?
X Which character type was chosen? Etc. . . ?)
X
XAlso, please tell me which version of UN*X you are running, and upon
Xwhich type of hardware.
X
XI will also do my best to help anyone with problems just trying to
Xget the game running. Again, I need to know which version of UN*X
Xand what type of CPU. Also, a copy of the output from 'make'
Xwould be extremely useful.
X
XAny and all ideas/suggestions/additions are more than welcome. If
Xyou feel strongly enough about it, write the change and send it to me,
Xand I will do my best to incorporate it in the next version of Phantasia.
XOtherwise, I will give serious thought to adding it myself.
X
XFollow the directions in the Makefile CAREFULLY to set up the game.
XRead the comments at the beginning of 'main.c', if you haven't already.
X
XEnjoy.
X
XTed Estes
XAT&T Information Systems
XSkokie, IL 60077
X
X...!ihnp4!ttrdc!ttrda!estes
!EOR!
echo x - Makefile
sed 's/^X//' > Makefile << '!EOR!'
X# Makefile for Phantasia 3.3.2
X#
X# To create game:
X#
X# 1) Set up a directory where the game and its support files will live.
X# (It is suggested that the source be kept somewhere else.)
X#
X# 2) Set up the variables in Makefile CAREFULLY to reflect your
X# particular situation.
X#
X# 3) Check out ok_to_play() at the end of main.c if you want to include
X# code to restrict access at certain times.
X#
X# 4) 'make install' and sit back and watch.
X#
X# NOTE: 'setup' MUST be executed before trying to run 'phantasia'.
X# The install procedure does this for you.
X#
X#
X# To convert from 3.3.1 or 3.3.1+ to 3.3.2:
X#
X# 1) 'make convert' (3.3.1+: 'make PLUS=-DPHANTPLUS convert')
X#
X# 2) Move 'newcharacs' to 'characs'.
X#
X
XRM = -rm
XSHAR = /d2/estes/bin/shar
X# Tell 'make' to use /bin/sh for all commands.
XSHELL = /bin/sh
X
X# PLOTDEVICE is used for plotting the map.
X# Change as appropriate.
XPLOTDEVICE = > /dev/tty
X
X# Add '-ljobs' to LDFLAGS if 4.1bsd; add -ltermlib if not SVR2.
X# Need separate i/d space on small machines.
X# May need '-f' on machines without floating point hardware.
XLDFLAGS = -lm -lcurses
X
X# DEST is where the program and its support files reside
XDEST = /a2/estes/phant
X
X# The following are program constants which are implementation dependent.
X#
X# DEST is passed on. Note that there is no closing quote here.
X# WIZARD is the login of the one who will clean up things.
X# UID is the uid of game wizard.
X# define OK_TO_PLAY to restrict playing access at certain times.
X# Also see function ok_to_play() in main.c, and tailor to your own needs.
X# define ENEMY to include code for checking of a 'hit list' of resricted
X# accounts. The list of logins goes in the file 'enemy'.
X# SHELL is the default shell for shell escapes. If SHELL is not defined,
X# shell escapes are not enabled.
X# define BSD41 for 4.1bsd
X# define BSD42 for 4.2bsd
X# define SYS3 for System III, or similar (like Version 7)
X# define SYS5 for System V
X# If you don't have 'strchr()', put '-Dstrchr=index' below.
X# May need '-I/usr/include/sys' for 4.2bsd.
XCFLAGS = -O \
X -DDEST=\"${DEST} \
X -DWIZARD=\"estes\" \
X -DUID=419 \
X -DOK_TO_PLAY \
X -DENEMY \
X -DSHELL=\"/bin/sh\" \
X -DSYS5
X
XCFILES = main.c fight.c io.c interplayer.c gamesupport.c misc.c phantglobs.c
XOFILES = main.o fight.o io.o interplayer.o gamesupport.o misc.o phantglobs.o
XHFILES = phantdefs.h phantstruct.h macros.h include.h
X
Xall: phantasia setup phant.help
X
X# Make the game.
Xphantasia: ${OFILES}
X ${CC} ${OFILES} ${LDFLAGS} -o phantasia
X
X${OFILES}: ${HFILES}
X
X# Make the initialization program.
Xsetup: phantglobs.o setup.o monsters.asc
X ${CC} phantglobs.o setup.o ${LDFLAGS} -o setup
X
Xsetup.o: ${HFILES}
X
X# Make documentation.
X# The flags below on tbl and nroff are to make a line printable version.
Xphant.help: phant.nr
X tbl -TX phant.nr | nroff -Ttn300 -man > phant.help
X
X# Install game and documentation. Initialize.
Xinstall: all
X cp phantasia phant.help ${DEST}
X chmod 755 ${DEST}
X chmod 4711 ${DEST}/phantasia
X chmod 644 ${DEST}/phant.help
X setup
X
X# Make Phantasia map.
X# Change the map commands reflect your installation.
X# Pre-System III installations may use 'plot' instead of 'tplot'.
Xmap: map.c
X cc -O map.c -lplot -o map
X map | tplot -t4014 ${PLOTDEVICE}
X
X# Convert old character file to new format.
X# 'convert' is meant to be run only once.
X# PLUS = PHANTPLUS for conversion from 3.3.1+.
Xconvert: convert.c oldplayer.h phantstruct.h
X ${CC} ${CFLAGS} ${PLUS} convert.c ${LDFLAGS} -o convert
X convert
X @echo "New data is in newcharacs."
X
X# Clean up directory after installation.
Xclean:
X ${RM} -f *.o phantasia phant.help phant.pt?
X
X# Make 'shell archives'.
X# All source files barely fit into 5 archives, and must be
X# carefully grouped to do so.
Xshar: ${CFILES} ${HFILES} phant.nr Makefile map.c convert.c oldplayer.h
X ${SHAR} README Makefile main.c include.h phantstruct.h \
X map.c monsters.asc > phant.pt1
X ${SHAR} phantglobs.h phantglobs.c fight.c \
X convert.c > phant.pt2
X ${SHAR} interplayer.c gamesupport.c io.c > phant.pt3
X ${SHAR} macros.h phantdefs.h setup.c misc.c \
X oldplayer.h > phant.pt4
X ${SHAR} phant.nr interplayer.c > phant.pt5
X
!EOR!
echo x - main.c
sed 's/^X//' > main.c << '!EOR!'
X/*
X * Phantasia 3.3.2 -- Interterminal fantasy game
X *
X * Edward A. Estes
X * AT&T, March 12, 1986
X */
X
X/* DISCLAIMER:
X *
X * This game is distributed for free as is. It is not guaranteed to work
X * in every conceivable environment. It is not even guaranteed to work
X * in ANY environment.
X *
X * This game is distributed without notice of copyright, therefore it
X * may be used in any manner the recipient sees fit. However, the
X * author assumes no responsibility for maintaining or revising this
X * game, in its original form, or any derivitives thereof.
X *
X * The author shall not be responsible for any loss, cost, or damage,
X * including consequential damage, caused by reliance on this material.
X *
X * The author makes no warranties, express or implied, including warranties
X * of merchantability or fitness for a particular purpose or use.
X *
X * AT&T is in no way connected with this game.
X */
X
X/*
X * The program allocates as much file space as it needs to store characters,
X * so the possibility exists for the character file to grow without bound.
X * The file is purged upon normal entry to try to avoid that problem.
X * A similar problem exists for energy voids. To alleviate the problem here,
X * the void file is cleared with every new king, and a limit is placed
X * on the size of the energy void file.
X */
X
X/*
X * Put one line of text into the file 'motd' for announcements, etc.
X */
X
X/*
X * If ENEMY is #defined, a list of restricted login names is checked
X * in the file 'enemy'. These names are listed, one per line, with
X * no trailing blanks.
X */
X
X/*
X * The scoreboard file is updated when someone dies, and keeps track
X * of the highest character to date for that login.
X * Being purged from the character file does not cause the scoreboard
X * to be updated.
X */
X
X/*
X * All source files are set up for 'vi' with shiftwidth=4, tabstop=8.
X */
X
X/**/
X
X/*
X * main.c Main routines for Phantasia
X */
X
X#include "include.h"
X
X/***************************************************************************
X/ FUNCTION NAME: main()
X/
X/ FUNCTION: initialize state, and call main process
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS:
X/ int argc - argument count
X/ char **argv - argument vector
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: monstlist(), checkenemy(), ok_to_play(), activelist(),
X/ throneroom(), checkbattle(), readmessage(), changestats(), writerecord(),
X/ tradingpost(), adjuststats(), recallplayer(), displaystats(), checktampered(),
X/ fabs(), rollnewplayer(), time(), exit(), sqrt(), floor(), wmove(),
X/ signal(), strcat(), purgeoldplayers(), getuid(), isatty(), wclear(),
X/ strcpy(), system(), altercoordinates(), cleanup(), waddstr(), procmain(),
X/ playinit(), leavegame(), localtime(), getanswer(), neatstuff(), initstate(),
X/ scorelist(), titlelist()
X/
X/ GLOBAL INPUTS: *Login, Throne, Wizard, Player, *stdscr, Changed, Databuf[],
X/ Fileloc, Helpfile[], Stattable[]
X/
X/ GLOBAL OUTPUTS: Wizard, Player, Changed, Fileloc, Timeout, *Statptr
X/
X/ DESCRIPTION:
X/ Process arguments, initialize program, and loop forever processing
X/ player input.
X/
X/***************************************************************************/
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
Xbool noheader = FALSE; /* set if don't want header */
Xbool headeronly = FALSE; /* set if only want header */
Xbool examine = FALSE; /* set if examine a character */
Xlong seconds; /* for time of day */
Xdouble dtemp; /* for temporary calculations */
X
X initstate(); /* init globals */
X
X#ifdef ENEMY
X checkenemy(); /* check if denied access */
X#endif
X
X /* process arguments */
X while (--argc && (*++argv)[0] == '-')
X switch ((*argv)[1])
X {
X case 's': /* short */
X noheader = TRUE;
X break;
X
X case 'H': /* Header */
X headeronly = TRUE;
X break;
X
X case 'a': /* all users */
X activelist();
X cleanup(TRUE);
X /*NOTREACHED*/
X
X case 'p': /* purge old players */
X purgeoldplayers();
X cleanup(TRUE);
X /*NOTREACHED*/
X
X case 'S': /* set 'Wizard' */
X Wizard = (getuid() == UID);
X break;
X
X case 'x': /* examine */
X examine = TRUE;
X break;
X
X case 'm': /* monsters */
X monstlist();
X cleanup(TRUE);
X /*NOTREACHED*/
X
X case 'b': /* scoreboard */
X scorelist();
X cleanup(TRUE);
X /*NOTREACHED*/
X
X case 'h': /* help */
X cleanup(FALSE);
X strcpy(Databuf, "cat ");
X system(strcat(Databuf, Helpfile));
X exit(0);
X /*NOTREACHED*/
X }
X
X if (!isatty(0)) /* don't let non-tty's play */
X cleanup(TRUE);
X /*NOTREACHED*/
X
X playinit(); /* set up to catch signals, init curses */
X
X if (examine)
X {
X changestats(FALSE);
X cleanup(TRUE);
X /*NOTREACHED*/
X }
X
X if (!noheader)
X {
X titlelist();
X purgeoldplayers(); /* clean up old characters */
X }
X
X if (headeronly)
X cleanup(TRUE);
X /*NOTREACHED*/
X
X#ifdef OK_TO_PLAY
X if (!ok_to_play())
X {
X mvaddstr(23, 27, "Sorry, you can't play now.\n");
X cleanup(TRUE);
X /*NOTREACHED*/
X }
X#endif
X
X do
X /* get the player structure filled */
X {
X Fileloc = -1L;
X
X mvaddstr(22, 17, "Do you have a character to run [Q = Quit] ? ");
X
X switch (getanswer("NYQ", FALSE))
X {
X case 'Y':
X Fileloc = recallplayer();
X break;
X
X case 'Q':
X cleanup(TRUE);
X /*NOTREACHED*/
X
X default:
X Fileloc = rollnewplayer();
X break;
X }
X clear();
X }
X while (Fileloc < 0L);
X
X if (Player.p_level > 5.0)
X /* low level players have long timeout */
X Timeout = TRUE;
X
X /* update some important player statistics */
X strcpy(Player.p_login, Login);
X time(&seconds);
X Player.p_lastused = localtime(&seconds)->tm_yday;
X Player.p_status = S_PLAYING;
X writerecord(&Player, Fileloc);
X
X Statptr = &Stattable[Player.p_type]; /* initialize pointer */
X
X /* catch interrupts */
X#ifdef BSD41
X sigset(SIGINT, interrupt);
X#endif
X#ifdef BSD42
X signal(SIGINT, interrupt);
X#endif
X#ifdef SYS3
X signal(SIGINT, interrupt);
X#endif
X#ifdef SYS5
X signal(SIGINT, interrupt);
X#endif
X
X altercoordinates(Player.p_x, Player.p_y, A_FORCED); /* set some flags */
X
X clear();
X
X for (;;)
X /* loop forever, processing input */
X {
X#ifdef OK_TO_PLAY
X if (!ok_to_play())
X {
X mvaddstr(6, 0, "Whoops! Can't play now.\n");
X leavegame();
X /*NOTREACHED*/
X }
X#endif
X
X adjuststats(); /* cleanup stats */
X
X if (Throne && Player.p_crowns == 0 && Player.p_specialtype != SC_KING)
X /* not allowed on throne -- move */
X {
X mvaddstr(5,0,"You're not allowed in the Lord's Chamber without a crown.\n");
X altercoordinates(0.0, 0.0, A_NEAR);
X }
X
X if (Player.p_status != S_CLOAKED
X /* not cloaked */
X && (dtemp = fabs(Player.p_x)) == fabs(Player.p_y)
X /* |x| = |y| */
X && !Throne)
X /* not on throne */
X {
X dtemp = sqrt(dtemp / 100.0);
X if (floor(dtemp) == dtemp)
X /* |x| / 100 == n*n; at a trading post */
X {
X tradingpost();
X clear();
X }
X }
X
X checktampered(); /* check for energy voids, etc. */
X checkbattle(); /* check for player to player battle */
X neatstuff(); /* gurus, medics, etc. */
X
X if (Player.p_status == S_CLOAKED)
X /* costs 3 mana per turn to be cloaked */
X if (Player.p_mana > 3.0)
X Player.p_mana -= 3.0;
X else
X /* ran out of mana, uncloak */
X {
X Player.p_status = S_PLAYING;
X Changed = TRUE;
X }
X
X if (Player.p_status != S_PLAYING && Player.p_status != S_CLOAKED)
X /* change status back to S_PLAYING */
X {
X Player.p_status = S_PLAYING;
X Changed = TRUE;
X }
X
X if (Changed)
X /* update file only if important stuff has changed */
X {
X writerecord(&Player, Fileloc);
X Changed = FALSE;
X continue;
X }
X
X readmessage(); /* read message, if any */
X
X displaystats(); /* print statistics */
X
X move(6, 0);
X
X if (Throne)
X /* maybe make king, print prompt, etc. */
X throneroom();
X
X /* print status line */
X addstr("1:Move 2:Players 3:Talk 4:Stats 5:Quit ");
X if (Player.p_level >= MEL_CLOAK && Player.p_magiclvl >= ML_CLOAK)
X addstr("6:Cloak ");
X if (Player.p_level >= MEL_TELEPORT && Player.p_magiclvl >= ML_TELEPORT)
X addstr("7:Teleport ");
X if (Player.p_specialtype >= SC_COUNCIL || Wizard)
X addstr("8:Intervene ");
X
X procmain(); /* process input */
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: initstate()
X/
X/ FUNCTION: initialize some important global variable
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: time(), fopen(), srand(), error(), getuid(), getlogin(),
X/ getpwuid()
X/
X/ GLOBAL INPUTS: Peoplefile[], Voidfile[], Messfile[], Monstfile[]
X/
X/ GLOBAL OUTPUTS: *Energyvoidfp, Echo, Marsh, *Login, Users, Beyond,
X/ Throne, Wizard, Changed, Okcount, Timeout, Windows, *Monstfp, *Messagefp,
X/ *Playersfp
X/
X/ DESCRIPTION:
X/ Set global flags, and open files which remain open.
X/
X/************************************************************************/
X
Xinitstate()
X{
X Beyond = FALSE;
X Marsh = FALSE;
X Throne = FALSE;
X Changed = FALSE;
X Wizard = FALSE;
X Timeout = FALSE;
X Users = 0;
X Windows = FALSE;
X Echo = TRUE;
X#ifdef OK_TO_PLAY
X Okcount = 0;
X#endif
X
X /* setup login name */
X if ((Login = getlogin()) == NULL)
X Login = getpwuid(getuid())->pw_name;
X
X /* open some files */
X if ((Playersfp = fopen(Peoplefile, "r+")) == NULL)
X error(Peoplefile);
X /*NOTREACHED*/
X
X if ((Monstfp = fopen(Monstfile, "r+")) == NULL)
X error(Monstfile);
X /*NOTREACHED*/
X
X if ((Messagefp = fopen(Messfile, "r")) == NULL)
X error(Messfile);
X /*NOTREACHED*/
X
X if ((Energyvoidfp = fopen(Voidfile, "r")) == NULL)
X error(Voidfile);
X /*NOTREACHED*/
X
X srand((unsigned) time((long *) NULL)); /* prime random numbers */
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: rollnewplayer()
X/
X/ FUNCTION: roll up a new character
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: initplayer(), allocrecord(), truncstring(), fabs(), wmove(),
X/ wclear(), sscanf(), strcmp(), genchar(), waddstr(), findname(), mvprintw(),
X/ getanswer(), getstring()
X/
X/ GLOBAL INPUTS: Other, Wizard, Player, *stdscr, Databuf[]
X/
X/ GLOBAL OUTPUTS: Echo
X/
X/ DESCRIPTION:
X/ Prompt player, and roll up new character.
X/
X/************************************************************************/
X
Xlong
Xrollnewplayer()
X{
Xint chartype; /* character type */
Xint ch; /* input */
X
X initplayer(&Player); /* initialize player structure */
X
X clear();
X mvaddstr(4, 21, "Which type of character do you want:");
X mvaddstr(8, 4, "1:Magic User 2:Fighter 3:Elf 4:Dwarf 5:Halfling 6:Experimento ");
X if (Wizard)
X addstr("7:Super ? ");
X else
X addstr("? ");
X
X chartype = getanswer("2134567", FALSE);
X
X do
X {
X genchar(chartype); /* roll up a character */
X
X /* print out results */
X mvprintw(12, 14,
X "Strength : %2.0f Quickness: %2.0f Mana : %2.0f\n",
X Player.p_strength, Player.p_quickness, Player.p_mana);
X mvprintw(13, 14,
X "Energy Level: %2.0f Brains : %2.0f Magic Level: %2.0f\n",
X Player.p_energy, Player.p_brains, Player.p_magiclvl);
X
X if (Player.p_type == C_EXPER || Player.p_type == C_SUPER)
X break;
X
X mvaddstr(14, 14, "Type '1' to keep >");
X ch = getanswer(" ", TRUE);
X }
X while (ch != '1');
X
X if (Player.p_type == C_EXPER || Player.p_type == C_SUPER)
X /* get coordinates for experimento */
X for (;;)
X {
X mvaddstr(16, 0, "Enter the X Y coordinates of your experimento ? ");
X getstring(Databuf, SZ_DATABUF);
X sscanf(Databuf, "%F %F", &Player.p_x, &Player.p_y);
X
X if (fabs(Player.p_x) > D_EXPER || fabs(Player.p_y) > D_EXPER)
X mvaddstr(17, 0, "Invalid coordinates. Try again.\n");
X else
X break;
X }
X
X for (;;)
X /* name the new character */
X {
X mvprintw(18, 0,
X "Give your character a name [up to %d characters] ? ", SZ_NAME - 1);
X getstring(Player.p_name, SZ_NAME);
X truncstring(Player.p_name); /* remove trailing blanks */
X
X if (Player.p_name[0] == '\0')
X /* no null names */
X mvaddstr(19, 0, "Invalid name.");
X else if (findname(Player.p_name, &Other) >= 0L)
X /* cannot have duplicate names */
X mvaddstr(19, 0, "Name already in use.");
X else
X /* name is acceptable */
X break;
X
X addstr(" Pick another.\n");
X }
X
X /* get a password for character */
X Echo = FALSE;
X
X do
X {
X mvaddstr(20, 0, "Give your character a password [up to 8 characters] ? ");
X getstring(Player.p_password, SZ_PASSWORD);
X mvaddstr(21, 0, "One more time to verify ? ");
X getstring(Databuf, SZ_PASSWORD);
X }
X while (strcmp(Player.p_password, Databuf) != 0);
X
X Echo = TRUE;
X
X return(allocrecord());
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: procmain()
X/
X/ FUNCTION: process input from player
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: dotampered(), changestats(), inputoption(), allstatslist(),
X/ fopen(), wmove(), random(), sscanf(), fclose(), altercoordinates(),
X/ waddstr(), fprintf(), distance(), userlist(), leavegame(), encounter(),
X/ getstring(), wclrtobot()
X/
X/ GLOBAL INPUTS: Circle, Illcmd[], Throne, Wizard, Player, *stdscr,
X/ Databuf[], Illmove[], Messfile[]
X/
X/ GLOBAL OUTPUTS: Player, Changed
X/
X/ DESCRIPTION:
X/ Process main menu options.
X/
X/************************************************************************/
X
Xprocmain()
X{
Xint ch; /* input */
Xdouble x; /* desired new x coordinate */
Xdouble y; /* desired new y coordinate */
Xdouble temp; /* for temporary calculations */
XFILE *fp; /* for opening files */
Xregister int loop; /* a loop counter */
Xbool hasmoved = FALSE; /* set if player has moved */
X
X ch = inputoption();
X mvaddstr(4, 0, "\n\n"); /* clear status area */
X
X move(7, 0);
X clrtobot(); /* clear data on bottom area of screen */
X
X if (Player.p_specialtype == SC_VALAR && (ch == '1' || ch == '7'))
X /* valar cannot move */
X ch = ' ';
X
X switch (ch)
X {
X case 'K': /* move up/north */
X case 'N':
X x = Player.p_x;
X y = Player.p_y + MAXMOVE();
X hasmoved = TRUE;
X break;
X
X case 'J': /* move down/south */
X case 'S':
X x = Player.p_x;
X y = Player.p_y - MAXMOVE();
X hasmoved = TRUE;
X break;
X
X case 'L': /* move right/east */
X case 'E':
X x = Player.p_x + MAXMOVE();
X y = Player.p_y;
X hasmoved = TRUE;
X break;
X
X case 'H': /* move left/west */
X case 'W':
X x = Player.p_x - MAXMOVE();
X y = Player.p_y;
X hasmoved = TRUE;
X break;
X
X default: /* rest */
X Player.p_energy += (Player.p_maxenergy + Player.p_shield) / 15.0
X + Player.p_level / 3.0 + 2.0;
X Player.p_energy =
X MIN(Player.p_energy, Player.p_maxenergy + Player.p_shield);
X
X if (Player.p_status != S_CLOAKED)
X /* cannot find mana if cloaked */
X {
X Player.p_mana += (Circle + Player.p_level) / 4.0;
X
X if (random() < 0.2 && Player.p_status == S_PLAYING && !Throne)
X /* wandering monster */
X encounter(-1);
X }
X break;
X
X case 'X': /* change/examine a character */
X changestats(TRUE);
X break;
X
X case '1': /* move */
X for (loop = 3; loop; --loop)
X {
X mvaddstr(4, 0, "X Y Coordinates ? ");
X getstring(Databuf, SZ_DATABUF);
X
X if (sscanf(Databuf, "%F %F", &x, &y) != 2)
X mvaddstr(5, 0, "Try again\n");
X else if (distance(Player.p_x, x, Player.p_y, y) > MAXMOVE())
X ILLMOVE();
X else
X {
X hasmoved = TRUE;
X break;
X }
X }
X break;
X
X case '2': /* players */
X userlist(TRUE);
X break;
X
X case '3': /* message */
X mvaddstr(4, 0, "Message ? ");
X getstring(Databuf, SZ_DATABUF);
X /* we open the file for writing to erase any data which is already there */
X fp = fopen(Messfile, "w");
X if (Databuf[0] != '\0')
X fprintf(fp, "%s: %s", Player.p_name, Databuf);
X fclose(fp);
X break;
X
X case '4': /* stats */
X allstatslist();
X break;
X
X case '5': /* good-bye */
X leavegame();
X /*NOTREACHED*/
X
X case '6': /* cloak */
X if (Player.p_level < MEL_CLOAK || Player.p_magiclvl < ML_CLOAK)
X ILLCMD();
X else if (Player.p_status == S_CLOAKED)
X Player.p_status = S_PLAYING;
X else if (Player.p_mana < MM_CLOAK)
X mvaddstr(5, 0, "No mana left.\n");
X else
X {
X Changed = TRUE;
X Player.p_mana -= MM_CLOAK;
X Player.p_status = S_CLOAKED;
X }
X break;
X
X case '7': /* teleport */
X /*
X * conditions for teleport
X * - 20 per (level plus magic level)
X * - OR council of the wise or valar or ex-valar
X * - OR transport from throne
X * transports from throne cost no mana
X */
X if (Player.p_level < MEL_TELEPORT || Player.p_magiclvl < ML_TELEPORT)
X ILLCMD();
X else
X for (loop = 3; loop; --loop)
X {
X mvaddstr(4, 0, "X Y Coordinates ? ");
X getstring(Databuf, SZ_DATABUF);
X
X if (sscanf(Databuf, "%F %F", &x, &y) == 2)
X {
X temp = distance(Player.p_x, x, Player.p_y, y);
X if (!Throne
X /* can transport anywhere from throne */
X && Player.p_specialtype <= SC_COUNCIL
X /* council, valar can transport anywhere */
X && temp > (Player.p_level + Player.p_magiclvl) * 20.0)
X /* can only move 20 per exp. level + mag. level */
X ILLMOVE();
X else
X {
X temp = (temp / 75.0 + 1.0) * 20.0; /* mana used */
X
X if (!Throne && temp > Player.p_mana)
X mvaddstr(5, 0, "Not enough power for that distance.\n");
X else
X {
X if (!Throne)
X Player.p_mana -= temp;
X hasmoved = TRUE;
X break;
X }
X }
X }
X }
X break;
X
X case 'C':
X case '9': /* monster */
X if (Throne)
X /* no monsters while on throne */
X mvaddstr(5, 0, "No monsters in the chamber!\n");
X else if (Player.p_specialtype != SC_VALAR)
X /* the valar cannot call monsters */
X {
X Player.p_sin += 1e-6;
X encounter(-1);
X }
X break;
X
X case '0': /* decree */
X if (Wizard || Player.p_specialtype == SC_KING && Throne)
X /* kings must be on throne to decree */
X dotampered();
X else
X ILLCMD();
X break;
X
X case '8': /* intervention */
X if (Wizard || Player.p_specialtype >= SC_COUNCIL)
X dotampered();
X else
X ILLCMD();
X break;
X }
X
X if (hasmoved)
X /* player has moved -- alter coordinates, and do random monster */
X {
X altercoordinates(x, y, A_SPECIFIC);
X
X if (random() < 0.2 && Player.p_status == S_PLAYING && !Throne)
X encounter(-1);
X }
X}
X/**/
X#ifdef ENEMY
X/************************************************************************
X/
X/ FUNCTION NAME: checkenemy()
X/
X/ FUNCTION: check login name against enemy list
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: fopen(), fgets(), strcmp(), fclose(), printf(), cleanup()
X/
X/ GLOBAL INPUTS: *Login, Databuf[], Enemyfile[]
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ The enemy file has a list of login names which are denied
X/ access to Phantasia.
X/ We scan this list and exit if the current login name is
X/ found in the list.
X/
X/************************************************************************/
X
Xcheckenemy()
X{
XFILE *fp; /* to open enemy file */
X
X /* check hit list of restricted accounts */
X if ((fp = fopen(Enemyfile, "r")) != NULL)
X {
X while (fgets(Databuf, SZ_DATABUF, fp) != NULL)
X if (strcmp(Login, Databuf) == 0)
X {
X printf ("The Phantasia privileges for the account \"%s\" have been revoked.\n", Login);
X printf ("Mail comments to %s.\n", WIZARD);
X fclose(fp);
X cleanup(TRUE);
X /*NOTREACHED*/
X }
X fclose (fp);
X }
X}
X#endif
X
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: titlelist()
X/
X/ FUNCTION: print title page
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: fread(), fseek(), fopen(), fgets(), wmove(), strcpy(),
X/ fclose(), strlen(), waddstr(), sprintf(), wrefresh()
X/
X/ GLOBAL INPUTS: Lines, Other, *stdscr, Databuf[], Lastdead[], Motdfile[],
X/ *Playersfp
X/
X/ GLOBAL OUTPUTS: Lines
X/
X/ DESCRIPTION:
X/ Print important information about game, players, etc.
X/
X/************************************************************************/
X
Xtitlelist()
X{
Xregister FILE *fp; /* used for opening various files */
Xbool councilfound = FALSE; /* set if we find a member of the council */
Xbool kingfound = FALSE; /* set if we find a king */
Xdouble hiexp, nxtexp; /* used for finding the two highest players */
Xdouble hilvl, nxtlvl; /* used for finding the two highest players */
Xchar hiname[21], nxtname[21];/* used for finding the two highest players */
X
X mvaddstr(0, 14, "W e l c o m e t o P h a n t a s i a (vers. 3.3.2)!");
X
X /* print message of the day */
X if ((fp = fopen(Motdfile, "r")) != NULL
X && fgets(Databuf, SZ_DATABUF, fp) != NULL)
X {
X mvaddstr(2, 40 - strlen(Databuf) / 2, Databuf);
X fclose(fp);
X }
X
X /* search for king */
X fseek(Playersfp, 0L, 0);
X while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
X if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED)
X /* found the king */
X {
X sprintf(Databuf, "The present ruler is %s Level:%.0f",
X Other.p_name, Other.p_level);
X mvaddstr(4, 40 - strlen(Databuf) / 2, Databuf);
X kingfound = TRUE;
X break;
X }
X
X if (!kingfound)
X mvaddstr(4, 24, "There is no ruler at this time.");
X
X /* search for valar */
X fseek(Playersfp, 0L, 0);
X while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
X if (Other.p_specialtype == SC_VALAR && Other.p_status != S_NOTUSED)
X /* found the valar */
X {
X sprintf(Databuf, "The Valar is %s Login: %s", Other.p_name, Other.p_login);
X mvaddstr(6, 40 - strlen(Databuf) / 2 , Databuf);
X break;
X }
X
X /* search for council of the wise */
X fseek(Playersfp, 0L, 0);
X Lines = 10;
X while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
X if (Other.p_specialtype == SC_COUNCIL && Other.p_status != S_NOTUSED)
X /* found a member of the council */
X {
X if (!councilfound)
X {
X mvaddstr(8, 30, "Council of the Wise:");
X councilfound = TRUE;
X }
X
X /* This assumes a finite (<=5) number of C.O.W.: */
X sprintf(Databuf, "%s Login: %s", Other.p_name, Other.p_login);
X mvaddstr(Lines++, 40 - strlen(Databuf) / 2, Databuf);
X }
X
X /* search for the two highest players */
X nxtname[0] = hiname[0] = '\0';
X hiexp = 0.0;
X nxtlvl = hilvl = 0;
X
X fseek(Playersfp, 0L, 0);
X while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1)
X if (Other.p_experience > hiexp && Other.p_specialtype <= SC_KING && Other.p_status != S_NOTUSED)
X /* highest found so far */
X {
X nxtexp = hiexp;
X hiexp = Other.p_experience;
X nxtlvl = hilvl;
X hilvl = Other.p_level;
X strcpy(nxtname, hiname);
X strcpy(hiname, Other.p_name);
X }
X else if (Other.p_experience > nxtexp
X && Other.p_specialtype <= SC_KING
X && Other.p_status != S_NOTUSED)
X /* next highest found so far */
X {
X nxtexp = Other.p_experience;
X nxtlvl = Other.p_level;
X strcpy(nxtname, Other.p_name);
X }
X
X mvaddstr(15, 28, "Highest characters are:");
X sprintf(Databuf, "%s Level:%.0f and %s Level:%.0f",
X hiname, hilvl, nxtname, nxtlvl);
X mvaddstr(17, 40 - strlen(Databuf) / 2, Databuf);
X
X /* print last to die */
X if ((fp = fopen(Lastdead,"r")) != NULL
X && fgets(Databuf, SZ_DATABUF, fp) != NULL)
X {
X mvaddstr(19, 25, "The last character to die was:");
X mvaddstr(20, 40 - strlen(Databuf) / 2,Databuf);
X fclose(fp);
X }
X
X refresh();
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: recallplayer()
X/
X/ FUNCTION: find a character on file
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: writerecord(), truncstring(), more(), death(), wmove(),
X/ wclear(), strcmp(), printw(), cleanup(), waddstr(), findname(), mvprintw(),
X/ getanswer(), getstring()
X/
X/ GLOBAL INPUTS: Player, *stdscr, Databuf[]
X/
X/ GLOBAL OUTPUTS: Echo, Player
X/
X/ DESCRIPTION:
X/ Search for a character of a certain name, and check password.
X/
X/************************************************************************/
X
Xlong
Xrecallplayer()
X{
Xlong loc = 0L; /* location in player file */
Xregister int loop; /* loop counter */
Xint ch; /* input */
X
X clear();
X mvprintw(10, 0, "What was your character's name ? ");
X getstring(Databuf, SZ_NAME);
X truncstring(Databuf);
X
X if ((loc = findname(Databuf, &Player)) >= 0L)
X /* found character */
X {
X Echo = FALSE;
X
X for (loop = 0; loop < 2; ++loop)
X {
X /* prompt for password */
X mvaddstr(11, 0, "Password ? ");
X getstring(Databuf, SZ_PASSWORD);
X if (strcmp(Databuf, Player.p_password) == 0)
X /* password good */
X {
X Echo = TRUE;
X
X if (Player.p_status != S_OFF)
X /* player did not exit normally last time */
X {
X clear();
X addstr("Your character did not exit normally last time.\n");
X addstr("If you think you have good cause to have your character saved,\n");
X printw("you may quit and mail your reason to '%s'.\n", WIZARD);
X addstr("Otherwise, continuing spells certain death.\n");
X addstr("Do you want to quit ? ");
X ch = getanswer("YN", FALSE);
X if (ch == 'Y')
X {
X Player.p_status = S_HUNGUP;
X writerecord(&Player, loc);
X cleanup(TRUE);
X /*NOTREACHED*/
X }
X death("Stupidity");
X /*NOTREACHED*/
X }
X return(loc);
X }
X else
X mvaddstr(12, 0, "No good.\n");
X }
X
X Echo = TRUE;
X }
X else
X mvaddstr(11, 0, "Not found.\n");
X
X more(13);
X return(-1L);
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: neatstuff()
X/
X/ FUNCTION: do random stuff
X/
X/ AUTHOR: E. A. Estes, 3/3/86
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: collecttaxes(), floor(), wmove(), random(), infloat(),
X/ waddstr(), mvprintw(), getanswer()
X/
X/ GLOBAL INPUTS: Player, *stdscr, *Statptr
X/
X/ GLOBAL OUTPUTS: Player
X/
X/ DESCRIPTION:
X/ Handle gurus, medics, etc.
X/
X/************************************************************************/
X
Xneatstuff()
X{
Xdouble temp; /* for temporary calculations */
Xint ch; /* input */
X
X switch ((int) ROLL(0.0, 100.0))
X {
X case 1:
X case 2:
X if (Player.p_poison > 0.0)
X {
X mvaddstr(4, 0, "You've found a medic! How much will you offer to be cured ? ");
X temp = floor(infloat());
X if (temp < 0.0 || temp > Player.p_gold)
X /* negative gold, or more than available */
X {
X mvaddstr(6, 0, "He was not amused, and made you worse.\n");
X Player.p_poison += 1.0;
X }
X else if (random() / 2.0 > (temp + 1.0) / MAX(Player.p_gold, 1))
X /* medic wants 1/2 of available gold */
X mvaddstr(5, 0, "Sorry, he wasn't interested.\n");
X else
X {
X mvaddstr(5, 0, "He accepted.");
X Player.p_poison = MAX(0.0, Player.p_poison - 1.0);
X Player.p_gold -= temp;
X }
X }
X break;
X
X case 3:
X mvaddstr(4, 0, "You've been caught raping and pillaging!\n");
X Player.p_experience += 4000.0;
X Player.p_sin += 0.5;
X break;
X
X case 4:
X temp = ROLL(10.0, 75.0);
X mvprintw(4, 0, "You've found %.0f gold pieces, want them ? ", temp);
X ch = getanswer("NY", FALSE);
X
X if (ch == 'Y')
X collecttaxes(temp, 0.0);
X break;
X
X case 5:
X if (Player.p_sin > 1.0)
X {
X mvaddstr(4, 0, "You've found a Holy Orb!\n");
X Player.p_sin -= 0.25;
X }
X break;
X
X case 6:
X if (Player.p_poison < 1.0)
X {
X mvaddstr(4, 0, "You've been hit with a plague!\n");
X Player.p_poison += 1.0;
X }
X break;
X
X case 7:
X mvaddstr(4, 0, "You've found some holy water.\n");
X ++Player.p_holywater;
X break;
X
X case 8:
X mvaddstr(4, 0, "You've met a Guru. . .");
X if (random() * Player.p_sin > 1.0)
X addstr("You disgusted him with your sins!\n");
X else if (Player.p_poison > 0.0)
X {
X addstr("He looked kindly upon you, and cured you.\n");
X Player.p_poison = 0.0;
X }
X else
X {
X addstr("He rewarded you for your virtue.\n");
X Player.p_mana += 50.0;
X Player.p_shield += 2.0;
X }
X break;
X
X case 9:
X mvaddstr(4, 0, "You've found an amulet.\n");
X ++Player.p_amulets;
X break;
X
X case 10:
X if (Player.p_blindness)
X {
X mvaddstr(4, 0, "You've regained your sight!\n");
X Player.p_blindness = FALSE;
X }
X break;
X
X default: /* deal with poison */
X if (Player.p_poison > 0.0)
X {
X temp = Player.p_poison * Statptr->c_weakness
X * Player.p_maxenergy / 600.0;
X if (Player.p_energy > Player.p_maxenergy / 10.0
X && temp + 5.0 < Player.p_energy)
X Player.p_energy -= temp;
X }
X break;
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: genchar()
X/
X/ FUNCTION: generate a random character
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS:
X/ int type - ASCII value of character type to generate
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: floor(), random()
X/
X/ GLOBAL INPUTS: Wizard, Player, Stattable[]
X/
X/ GLOBAL OUTPUTS: Player
X/
X/ DESCRIPTION:
X/ Use the lookup table for rolling stats.
X/
X/************************************************************************/
X
Xgenchar(type)
Xint type;
X{
Xregister int subscript; /* used for subscripting into Stattable */
Xregister struct charstats *statptr;/* for pointing into Stattable */
X
X subscript = type - '1';
X
X if (subscript < C_MAGIC || subscript > C_EXPER)
X if (subscript != C_SUPER || !Wizard)
X /* fighter is default */
X subscript = C_FIGHTER;
X
X statptr = &Stattable[subscript];
X
X Player.p_quickness =
X ROLL(statptr->c_quickness.base, statptr->c_quickness.interval);
X Player.p_strength =
X ROLL(statptr->c_strength.base, statptr->c_strength.interval);
X Player.p_mana =
X ROLL(statptr->c_mana.base, statptr->c_mana.interval);
X Player.p_maxenergy =
X Player.p_energy =
X ROLL(statptr->c_energy.base, statptr->c_energy.interval);
X Player.p_brains =
X ROLL(statptr->c_brains.base, statptr->c_brains.interval);
X Player.p_magiclvl =
X ROLL(statptr->c_magiclvl.base, statptr->c_magiclvl.interval);
X
X Player.p_type = subscript;
X
X if (Player.p_type == C_HALFLING)
X /* give halfling some experience */
X Player.p_experience = ROLL(600.0, 200.0);
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: playinit()
X/
X/ FUNCTION: initialize for playing game
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: signal(), wclear(), noecho(), crmode(), initscr(),
X/ wrefresh()
X/
X/ GLOBAL INPUTS: *stdscr, ill_sig()
X/
X/ GLOBAL OUTPUTS: Windows
X/
X/ DESCRIPTION:
X/ Catch a bunch of signals, and turn on curses stuff.
X/
X/************************************************************************/
X
Xplayinit()
X{
X /* catch/ingnore signals */
X
X#ifdef BSD41
X sigignore(SIGQUIT);
X sigignore(SIGALRM);
X sigignore(SIGTERM);
X sigignore(SIGTSTP);
X sigignore(SIGTTIN);
X sigignore(SIGTTOU);
X sighold(SIGINT);
X sigset(SIGHUP, ill_sig);
X sigset(SIGTRAP, ill_sig);
X sigset(SIGIOT, ill_sig);
X sigset(SIGEMT, ill_sig);
X sigset(SIGFPE, ill_sig);
X sigset(SIGBUS, ill_sig);
X sigset(SIGSEGV, ill_sig);
X sigset(SIGSYS, ill_sig);
X sigset(SIGPIPE, ill_sig);
X#endif
X#ifdef BSD42
X signal(SIGQUIT, SIG_IGN);
X signal(SIGALRM, SIG_IGN);
X signal(SIGTERM, SIG_IGN);
X signal(SIGTSTP, SIG_IGN);
X signal(SIGTTIN, SIG_IGN);
X signal(SIGTTOU, SIG_IGN);
X signal(SIGINT, SIG_IGN);
X signal(SIGHUP, ill_sig);
X signal(SIGTRAP, ill_sig);
X signal(SIGIOT, ill_sig);
X signal(SIGEMT, ill_sig);
X signal(SIGFPE, ill_sig);
X signal(SIGBUS, ill_sig);
X signal(SIGSEGV, ill_sig);
X signal(SIGSYS, ill_sig);
X signal(SIGPIPE, ill_sig);
X#endif
X#ifdef SYS3
X signal(SIGINT, SIG_IGN);
X signal(SIGQUIT, SIG_IGN);
X signal(SIGTERM, SIG_IGN);
X signal(SIGALRM, SIG_IGN);
X signal(SIGHUP, ill_sig);
X signal(SIGTRAP, ill_sig);
X signal(SIGIOT, ill_sig);
X signal(SIGEMT, ill_sig);
X signal(SIGFPE, ill_sig);
X signal(SIGBUS, ill_sig);
X signal(SIGSEGV, ill_sig);
X signal(SIGSYS, ill_sig);
X signal(SIGPIPE, ill_sig);
X#endif
X#ifdef SYS5
X signal(SIGINT, SIG_IGN);
X signal(SIGQUIT, SIG_IGN);
X signal(SIGTERM, SIG_IGN);
X signal(SIGALRM, SIG_IGN);
X signal(SIGHUP, ill_sig);
X signal(SIGTRAP, ill_sig);
X signal(SIGIOT, ill_sig);
X signal(SIGEMT, ill_sig);
X signal(SIGFPE, ill_sig);
X signal(SIGBUS, ill_sig);
X signal(SIGSEGV, ill_sig);
X signal(SIGSYS, ill_sig);
X signal(SIGPIPE, ill_sig);
X#endif
X
X initscr(); /* turn on curses */
X noecho(); /* do not echo input */
X crmode(); /* do not process erase, kill */
X clear();
X refresh();
X Windows = TRUE; /* mark the state */
X}
X
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: cleanup()
X/
X/ FUNCTION: close some files, and maybe exit
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS:
X/ bool doexit - exit flag
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: exit(), wmove(), fclose(), endwin(), nocrmode(), wrefresh()
X/
X/ GLOBAL INPUTS: *Energyvoidfp, LINES, *stdscr, Windows, *Monstfp,
X/ *Messagefp, *Playersfp
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Close all open files. If we are "in curses" terminate curses.
X/ If 'doexit' is set, exit, otherwise return.
X/
X/************************************************************************/
X
Xcleanup(doexit)
Xbool doexit;
X{
X if (Windows)
X {
X move(LINES - 2, 0);
X refresh();
X nocrmode();
X endwin();
X }
X
X fclose(Playersfp);
X fclose(Monstfp);
X fclose(Messagefp);
X fclose(Energyvoidfp);
X
X if (doexit)
X exit(0);
X /*NOTREACHED*/
X}
X/**/
X#ifdef OK_TO_PLAY
X#include <sys/types.h>
X#include <utmp.h> /* used for counting users on system */
X
X/************************************************************************
X/
X/ FUNCTION NAME: ok_to_play()
X/
X/ FUNCTION: indicate whether playing is allowed
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE:
X/ FALSE if playing is not allowed
X/ TRUE if playing is allowed
X/
X/ MODULES CALLED: time(), fread(), fopen(), fclose(), localtime()
X/
X/ GLOBAL INPUTS: Wizard, Okcount
X/
X/ GLOBAL OUTPUTS: Okcount
X/
X/ DESCRIPTION:
X/ This function is provided to allow one to restrict access to the game.
X/ Tailor this routine as appropriate.
X/ Return FALSE if playing is not allowed at this time.
X/
X/************************************************************************/
X
Xok_to_play()
X{
Xregister struct tm *tp; /* to get time of day */
Xregister int numusers = 0; /* number of users on system */
XFILE *fp; /* to open files */
Xlong now; /* present time */
Xstruct utmp ubuf; /* to read 'utmp' file */
X
X if (Wizard)
X /* wizard can always play */
X return(TRUE);
X
X if (Okcount >= 5)
X Okcount = 0;
X if (Okcount++ > 0)
X /* only check every 5 times */
X return(TRUE);
X
X /* check time of day */
X time(&now);
X tp = localtime(&now);
X if (((tp->tm_hour > 8 && tp->tm_hour < 12) /* 8-noon */
X || (tp->tm_hour > 12 && tp->tm_hour < 16)) /* 1-4 pm */
X && (tp->tm_wday != 0 && tp->tm_wday != 6)) /* not a weekend */
X return(FALSE);
X
X /* check # of users */
X if ((fp = fopen("/etc/utmp", "r")) != NULL)
X {
X while (fread((char *) &ubuf, sizeof(ubuf), 1, fp) == 1)
X#ifdef SYS5
X if (ubuf.ut_type == USER_PROCESS)
X#else
X if (ubuf.ut_name[0] != '\0')
X#endif
X ++numusers;
X fclose(fp);
X
X if (numusers > N_MAXUSERS)
X return(FALSE);
X }
X return(TRUE);
X}
X#endif
!EOR!
echo x - include.h
sed 's/^X//' > include.h << '!EOR!'
X/*
X * include.h - includes all important files for Phantasia
X */
X
X#include <ctype.h>
X#include <curses.h>
X#include <math.h>
X#include <pwd.h>
X#include <setjmp.h>
X#include <signal.h>
X#include <time.h>
X
X#include "macros.h"
X#include "phantdefs.h"
X#include "phantstruct.h"
X#include "phantglobs.h"
!EOR!
echo x - phantstruct.h
sed 's/^X//' > phantstruct.h << '!EOR!'
X/*
X * phantstruct.h - structure definitions for Phantasia
X */
X
Xstruct player /* player statistics */
X {
X double p_experience; /* experience */
X double p_level; /* level */
X double p_strength; /* strength */
X double p_sword; /* sword */
X double p_might; /* effect strength */
X double p_energy; /* energy */
X double p_maxenergy; /* maximum energy */
X double p_shield; /* shield */
X double p_quickness; /* quickness */
X double p_quksilver; /* quicksilver */
X double p_speed; /* effective quickness */
X double p_magiclvl; /* magic level */
X double p_mana; /* mana */
X double p_brains; /* brains */
X double p_poison; /* poison */
X double p_gold; /* gold */
X double p_gems; /* gems */
X double p_sin; /* sin */
X double p_x; /* x coord */
X double p_y; /* y coord */
X double p_1scratch,
X p_2scratch; /* variables used for decree, player battle */
X
X struct
X {
X short ring_type; /* type of ring */
X short ring_duration; /* duration of ring */
X bool ring_inuse; /* ring in use flag */
X } p_ring; /* ring stuff */
X
X long p_age; /* age of player */
X
X int p_degenerated; /* age/3000 last degenerated */
X
X short p_type; /* character type */
X short p_specialtype; /* special character type */
X short p_lives; /* multiple lives for council, valar */
X short p_crowns; /* crowns */
X short p_charms; /* charms */
X short p_amulets; /* amulets */
X short p_holywater; /* holy water */
X short p_lastused; /* day of year last used */
X short p_status; /* playing, cloaked, etc. */
X short p_tampered; /* decree'd, etc. flag */
X short p_istat; /* used for inter-terminal battle */
X
X bool p_palantir; /* palantir */
X bool p_blessing; /* blessing */
X bool p_virgin; /* virgin */
X bool p_blindness; /* blindness */
X
X char p_name[SZ_NAME]; /* name */
X char p_password[SZ_PASSWORD];/* password */
X char p_login[SZ_LOGIN]; /* login */
X };
X
Xstruct monster /* monster stats */
X {
X double m_strength; /* strength */
X double m_brains; /* brains */
X double m_speed; /* speed */
X double m_energy; /* energy */
X double m_experience; /* experience */
X double m_flock; /* % chance of flocking */
X
X double m_o_strength; /* original strength */
X double m_o_speed; /* original speed */
X double m_maxspeed; /* maximum speed */
X double m_o_energy; /* original energy */
X double m_melee; /* melee damage */
X double m_skirmish; /* skirmish damage */
X
X int m_treasuretype; /* treasure type */
X int m_type; /* special type */
X
X char m_name[26]; /* name */
X };
X
Xstruct energyvoid /* energy void */
X {
X double ev_x; /* x coordinate */
X double ev_y; /* y coordinate */
X bool ev_active; /* active or not */
X };
X
Xstruct scoreboard /* scoreboard entry */
X {
X double sb_level; /* level of player */
X char sb_type[4]; /* character type of player */
X char sb_name[SZ_NAME]; /* name of player */
X char sb_login[SZ_LOGIN]; /* login of player */
X };
X
Xstruct charstats /* character type statistics */
X {
X double c_maxbrains; /* max brains per level */
X double c_maxmana; /* max mana per level */
X double c_weakness; /* how strongly poison affects player */
X double c_goldtote; /* how much gold char can carry */
X int c_ringduration; /* bad ring duration */
X struct
X {
X double base; /* base for roll */
X double interval; /* interval for roll */
X double increase; /* increment per level */
X } c_quickness, /* quickness */
X c_strength, /* strength */
X c_mana, /* mana */
X c_energy, /* energy level */
X c_brains, /* brains */
X c_magiclvl; /* magic level */
X };
X
Xstruct menuitem /* menu item for purchase */
X {
X char *item; /* menu item name */
X double cost; /* cost of item */
X };
!EOR!
echo x - map.c
sed 's/^X//' > map.c << '!EOR!'
X#define minusminus plusplus
X#define minusplus plusminus
X
Xmain()
X{
X /* Set up */
X
X openpl();
X space(-1400, -1000, 1200, 1200);
X
X /* Big box */
X
X move(-1400, -1000);
X cont(-1400, 1000);
X cont(600, 1000);
X cont(600, -1000);
X cont(-1400, -1000);
X
X /* Grid -- horizontal lines every 200 */
X
X linemod("dotted");
X line(600, -800, -1400, -800);
X line(-1400, -600, 600, -600);
X line(600, -400, -1400, -400);
X line(-1400, -200, 600, -200);
X linemod("solid");
X line(600, 0, -1400, 0);
X linemod("dotted");
X line(-1400, 200, 600, 200);
X line(600, 400, -1400, 400);
X line(-1400, 600, 600, 600);
X line(600, 800, -1400, 800);
X
X /* Grid -- vertical lines every 200 */
X
X line(-1200, 1000, -1200, -1000);
X line(-1000, 1000, -1000, -1000);
X line(-800, 1000, -800, -1000);
X line(-600, 1000, -600, -1000);
X linemod("solid");
X line(-400, 1000, -400, -1000);
X linemod("dotted");
X line(-200, 1000, -200, -1000);
X line(0, 1000, 0, -1000);
X line(200, 1000, 200, -1000);
X line(400, 1000, 400, -1000);
X
X /* Circles radius +250 on "center" */
X
X linemod("solid");
X circle(-400, 0, 250);
X circle(-400, 0, 500);
X circle(-400, 0, 750);
X circle(-400, 0, 1000);
X
X /* A few labels */
X
X move(-670, 1075);
X label("- THE PHANTASIA UNIVERSE -");
X line(-630, 1045, -115, 1045);
X move(-360, 80);
X label("Lorien");
X move(-385, -100);
X label("Ithilien");
X move(-560, 80);
X label("Rohan");
X move(-580, -100);
X label("Anorien");
X plusplus("Rovanion", -250, 320);
X plusplus("The Iron Hills", -100, 560);
X plusplus("Rhun", 250, 570);
X minusplus("Dunland", -700, 160);
X minusplus("Eriador", -920, 300);
X minusplus("The Northern Waste", -1240, 320);
X minusminus("Gondor", -720, -180);
X minusminus("South Gondor", -940, -270);
X minusminus("Far Harad", -1100, -500);
X plusminus("Mordor", -180, -300);
X plusminus("Khand", 0, -500);
X plusminus("Near Harad", 40, -780);
X move(340, 900);
X label("The Moors");
X move(300, 840);
X label("Adventurous");
X move(340, -840);
X label("The Moors");
X move(300, -900);
X label("Adventurous");
X move(-1340, 900);
X label("The Moors");
X move(-1340, 840);
X label("Adventurous");
X move(-1340, -840);
X label("The Moors");
X move(-1340, -900);
X label("Adventurous");
X move(700, 1000);
X label("OUTER CIRCLES:");
X line(690, 970, 1000, 970);
X move(700, 900);
X label("> 9: The Outer Waste");
X move(700, 800);
X label("> 20: The Dead Marshes");
X move(700, 700);
X label("> 35: Kennaquhair");
X move(700, 600);
X label("> 55: Morannon");
X move(700, 300);
X label("(0,0): The Lord's Chamber");
X
X move(700, -400);
X label("Grid squares are 100 x 100");
X move(700, -800);
X label("Created by Ted Estes");
X move(700, -860);
X label("Plotted by Chris Robertson");
X move(700, -920);
X label(" c 1985");
X circle(723, -923, 20);
X
X /* Close down */
X
X move(-1380, 1180);
X closepl();
X exit(0);
X}
X
Xplusplus(s, x, y) /* draw strings in plus plus quadrant */
Xchar *s;
Xint x, y;
X{
Xchar s1[2];
X
X while (*s)
X {
X move(x, y);
X s1[0] = *s++;
X s1[1] = '\0';
X label(s1);
X x += 25;
X y -= 30;
X }
X}
X
Xplusminus(s, x, y) /* draw strings in plus minus quadrant */
Xchar *s;
Xint x, y;
X{
Xchar s1[2];
X
X while (*s)
X {
X move(x, y);
X s1[0] = *s++;
X s1[1] = '\0';
X label(s1);
X x += 25;
X y += 30;
X }
X}
!EOR!
echo x - monsters.asc
sed 's/^X//' > monsters.asc << '!EOR!'
XA Water Leaper 12 14 16 24 59 0 0 62
XA Leech 4 19 29 30 66 0 0 73
XAn Urisk 13 30 15 46 127 1 0 3
XShellycoat 28 21 18 63 226 2 0 0
XA Naiad 21 62 27 58 378 2 0 11
XA Nixie 22 58 28 108 604 3 0 6
XA Glaistig 21 106 25 127 1002 3 0 0
XA Mermaid 18 116 22 108 809 3 0 0
XA Merman 24 115 23 109 808 4 0 0
XA Siren 22 128 31 89 915 4 0 24
XA Lamprey 14 67 33 156 1562 4 15 37
XA Kopoacinth 26 36 26 206 2006 5 0 20
XA Kelpie 61 25 24 223 4025 5 0 0
XAn Aspidchelone 114 104 19 898 10041 7 0 2
XAn Idiot 13 14 16 28 49 0 0 0
XSome Green Slime 1 5 45 100 57 0 0 26
XA Pixie 11 29 23 26 64 0 0 32
XA Serpent 10 18 25 25 79 0 0 10
XA Cluricaun 12 27 20 30 81 0 14 5
XAn Imp 22 30 14 40 92 0 0 1
XA Centipede 3 8 18 15 33 0 0 61
XA Beetle 2 11 21 26 44 0 0 48
XA Fir Darrig 18 22 17 35 107 0 14 1
XModnar 15 23 20 40 101 7 2 12
XA Gnome 7 45 26 23 111 0 0 21
XA Sprite 9 37 25 31 132 1 0 43
XA Mimic 11 55 29 47 213 1 3 2
XA Kobold 13 10 14 21 121 1 12 68
XA Spider 6 11 28 28 124 1 0 57
XAn Uldra 14 37 21 32 93 1 0 6
XA Gnoll 20 25 15 40 166 1 0 61
XA Bogie 23 28 19 57 189 1 0 57
XA Fachan 9 40 15 45 139 1 14 10
XA Moron 3 1 10 10 28 0 0 100
XAn Orc 25 13 16 26 141 1 0 92
XA Ghillie Dhu 12 16 13 28 104 2 14 2
XA Bogle 19 15 16 35 157 2 14 15
XA Shrieker 2 62 27 9 213 2 16 0
XA Carrion Crawler 12 20 20 65 142 2 0 42
XA Trow 15 17 23 51 136 2 0 36
XA Warg 20 10 17 45 152 2 0 88
XA Stirge 2 6 35 25 153 2 0 95
XA Crebain 5 11 31 31 82 2 0 81
XA Killmoulis 30 19 8 75 175 3 14 22
XA Hob-goblin 35 20 15 72 246 3 0 18
XA Unicorn 27 57 27 57 627 3 1 0
XA Fenoderee 16 6 21 65 222 3 0 42
XAn Ogre 42 14 16 115 409 3 0 19
XA Dodo 62 12 11 76 563 3 0 3
XA Hydra 14 27 33 99 599 3 0 27
XA Hamadryad 23 47 26 62 426 3 0 12
XA Bwca 21 17 19 55 387 3 14 1
XAn Owlbear 35 16 18 100 623 4 0 22
XBlack Annis 37 52 15 65 786 4 0 2
XA Jello Blob 100 25 7 264 1257 4 0 13
XA Jubjub Bird 45 23 12 114 1191 4 0 0
XA Wichtlein 13 40 25 61 800 4 0 8
XA Cocodrill 39 28 24 206 1438 4 0 38
XA Troll 75 12 20 185 1013 4 24 29
XA Bonnacon 89 26 9 255 1661 4 17 14
XA Gargoyle 22 21 29 200 1753 5 0 7
XA Chaladrius 8 49 37 172 1929 5 0 20
XA Gwyllion 27 73 20 65 1888 5 0 4
XA Cinomulgus 23 2 10 199 263 5 0 18
XA Peridexion 26 32 24 98 1300 5 0 2
XSmeagol 41 33 27 373 2487 5 18 0
XA Wraith 52 102 22 200 3112 5 25 13
XA Snotgurgle 143 19 26 525 4752 6 0 3
XA Phooka 42 63 21 300 4125 5 0 12
XA Vortex 101 30 31 500 6992 6 9 4
XShelob 147 64 28 628 5003 7 13 0
XA Thaumaturgist 35 200 23 400 7628 6 7 0
XSmaug 251 76 26 1022 9877 7 0 0
XA Cold-drake 301 102 24 1222 10888 7 0 0
XA Red Dragon 342 141 23 1299 11649 8 0 0
XScatha the Worm 406 208 20 1790 11999 8 0 0
XTiamat 506 381 29 2000 13001 9 11 0
XA Bandersnatch 105 98 22 450 7981 6 0 3
XA Harpy 103 49 24 263 7582 6 0 2
XA Tigris 182 38 17 809 7777 6 0 3
XA Gryphon 201 45 19 813 8888 7 0 1
XA Coblynau 205 46 18 585 8333 6 0 2
XA Chimaera 173 109 28 947 12006 7 0 0
XA Jack-in-Irons 222 36 12 1000 9119 7 0 0
XSaruman 55 373 17 1500 17101 11 6 0
XA Balrog 500 100 25 705 8103 7 8 0
XArgus 201 87 14 1500 10010 8 0 0
XA Titan 302 1483 12 1625 11011 8 0 0
XCacus 256 43 19 1750 12012 8 0 0
XBegion 403 154 10 1875 13013 8 0 0
XGrendel 197 262 23 2000 14014 8 0 0
XA Nazgul 250 251 26 1011 9988 12 10 9
XA Succubus 186 1049 27 2007 19984 9 19 0
XRed Cap 143 50 35 1965 23456 9 0 0
XA Nuckelavee 300 75 20 2185 11111 8 0 0
XCerberus 236 96 29 2600 25862 9 20 0
XA Jabberwock 185 136 25 2265 23256 9 22 0
XUngoliant 399 2398 37 2784 27849 10 21 0
XLeanan-Sidhe 486 5432 46 3000 30004 9 5 0
XThe Dark Lord 9999 9999 31 19999 30005 13 4 0
!EOR!